Skip to content

박은진 week3#42

Merged
bk-git-hub merged 6 commits intoEunjin-nfrom
Eunjin-n-week3
Apr 4, 2026
Merged

박은진 week3#42
bk-git-hub merged 6 commits intoEunjin-nfrom
Eunjin-n-week3

Conversation

@Eunjin-n
Copy link
Copy Markdown

@Eunjin-n Eunjin-n commented Apr 2, 2026

✅ 제출 정보

  • Week: Week <03>

✅ 체크리스트 (필수)

  • PR의 base branchmain이 아니라 내 GitHub 핸들 브랜치(<handle>)다
  • compare branch가 <handle>-week-xx 형식이다
  • 변경 사항이 이번 주 과제 범위에 해당한다
  • (필요 시) 실행 방법을 적었다
  • (가능하면) 결과 스크린샷/데모 링크를 첨부했다

🧩 구현 내용 요약

  • 할 일 추가/삭제 기능 구현
image image image

❓ 궁금한 점

  • 함수를 어느 컴포넌트에서 선언하고 사용해야 하는지 구별하기가 어렵습니다 (_ _ (

Copy link
Copy Markdown
Collaborator

@bk-git-hub bk-git-hub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

은진님 고생 많으셨습니다!

이번주 핵심적인 컴포넌트 분리랑 state 위치 잡는 방향을 전반적으로 잘 잡으셨어요. 특히 todos를 App에 두고 입력값은 TodoInput에서 관리한 점은 이번 주 핵심을 잘 반영한 구현이에요.

이번주 코멘트는 일부 수정하면 좋을 부분들을 남겨두었습니다

질문에 대한 답변입니다
어떤 함수가 어느 위치에 있어야 하는지는 “어떤 state를 누가 소유하고 있느냐”를 기준으로 보면 훨씬 정리하기 쉬워요.
보통 shared state는 그 state를 소유한 컴포넌트(또는 가장 가까운 공통 부모)에 두고, 해당 state를 갱신하는 handler도 그 근처에 둡니다. 자식 컴포넌트는 props로 전달받아 실행만 하는 경우가 많아요.

이번 코드에서는 todos를 App이 관리하고 있으니 addTodo, deleteTodo 같은 함수도 App에 두는 구조가 가장 자연스럽습니다.

반면 문자열 가공, 날짜 포맷팅, 공통 계산처럼 UI 상태와 직접 연결되지 않은 순수 함수들은 lib/utils.ts 같은 별도 파일로 분리하는 편이 좋습니다 :)

<del>{text}</del>
</div>
{name}
<button className="delBtn">🗑</button>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

완료된 항목 쪽 삭제 버튼에는 onClick이 연결되어 있지 않아서, 지금은 완료된 todo를 삭제할 수 없어요. 완료 여부와 관계없이 같은 삭제 핸들러가 연결되도록 맞춰 주세요

Comment on lines +17 to +20
function handleFocus() {
if (text === "") {
setText("새로운 할 일");
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

포커스할 때 새로운 할 일을 실제 input state로 넣으면, 사용자가 아무 것도 입력하지 않아도 그 문구가 그대로 추가될 수 있어요. 이 문구는 placeholder처럼만 보이게 하면 더 좋을 것같아요.

Comment on lines +17 to +27
function deleteTodo(id: number) {
const result = [];

for (let i = 0; i < todos.length; i++) {
if (todos[i].id !== id) {
result.push(todos[i]);
}
}

setTodos(result);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서는 직접 for문으로 새 배열을 만드는 것보다 todos.filter((todo) => todo.id !== id)처럼 쓰면, '이 id만 제외한다'는 의도가 더 바로 보여서 읽기 쉬워져요

Comment on lines 36 to 77
@@ -76,6 +76,52 @@ body {
line-height: 21px;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 클래스 명이 바뀌었는데 아직까지 text 클래스만 사용중인걸로 보여요. 스타일이 실제로 잘 적용되는지 확인해보면 좋을 것 같아요.

Comment on lines +20 to 43
if (completed) {
return (
<li className={`item checked`}>
<div className="CheckedBox">
<svg
className="CheckedIcon"
xmlns="http://www.w3.org/2000/svg"
width="14"
height="10"
viewBox="0 0 14 10"
fill="none"
>
<g clip-path="url(#clip0_16_101)">
<path
d="M1 5L5 9L13 1"
stroke="white"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_16_101">
<rect width="14" height="10" fill="white" />
</clipPath>
</defs>
</svg>
<img src={checkedIcon} alt="checked" />
</div>
<div className="text">
<del>{text}</del>
</div>
{name}
<button className="delBtn">🗑</button>
</li>
);
}

return (
<li className="item">
<div className="UncheckedBox"></div>
{name}
<div className="text">{text}</div>
<button className="delBtn" onClick={handleClick}>
🗑
</button>
</li>
);
}
Copy link
Copy Markdown
Collaborator

@bk-git-hub bk-git-hub Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (completed) {
return (
<li className={`item checked`}>
<div className="CheckedBox">
<svg
className="CheckedIcon"
xmlns="http://www.w3.org/2000/svg"
width="14"
height="10"
viewBox="0 0 14 10"
fill="none"
>
<g clip-path="url(#clip0_16_101)">
<path
d="M1 5L5 9L13 1"
stroke="white"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_16_101">
<rect width="14" height="10" fill="white" />
</clipPath>
</defs>
</svg>
<img src={checkedIcon} alt="checked" />
</div>
<div className="text">
<del>{text}</del>
</div>
{name}
<button className="delBtn">🗑</button>
</li>
);
}
return (
<li className="item">
<div className="UncheckedBox"></div>
{name}
<div className="text">{text}</div>
<button className="delBtn" onClick={handleClick}>
🗑
</button>
</li>
);
}
return (
<li className={`item ${completed ? "checked" : ""}`}>
<div className={completed ? "CheckedBox" : "UncheckedBox"}>
{completed && <img src={checkedIcon} alt="" />}
</div>
<div className="text">{completed ? <del>{text}</del> : text}</div>
<button className="delBtn" onClick={handleClick}>
🗑
</button>
</li>
);
}

Comment on lines +17 to +25
function deleteTodo(id: number) {
const result = [];

for (let i = 0; i < todos.length; i++) {
if (todos[i].id !== id) {
result.push(todos[i]);
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addTodo, deleteTodo도 동작은 잘 전달되지만, 이벤트를 처리하는 함수라는 점이 더 잘 드러나도록 handleAddTodo, handleDeleteTodo처럼 이름을 지어보는 것도 좋아요. 그리고 자식 컴포넌트에 props로 넘길 때는 onDelete처럼 역할이 보이는 이름을 쓰면, 이건 콜백 props구나가 더 바로 읽힙니다.

@bk-git-hub bk-git-hub merged commit 35d0308 into Eunjin-n Apr 4, 2026
5 checks passed
@bk-git-hub bk-git-hub deleted the Eunjin-n-week3 branch April 4, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants